#include "rt_app.h"
#include "cuda_support.h"

namespace fmrt
{
	GPURayTracerApp::GPURayTracerApp()
	{

	}
	
	GPURayTracerApp::~GPURayTracerApp()
	{

	}
	
	int GPURayTracerApp::queryDevice()
	{
		Ogre::LogManager::getSingleton().logMessage("*** Query CUDA Device ***"); 
		
		// get CUDA device count
		int deviceCount = 0; 
		if (cudaGetDeviceCount(&deviceCount) != cudaSuccess) 
		{
			Ogre::LogManager::getSingleton().logMessage("FAILED! cudaGetDeviceCount() CUDA Driver and Runtime version may be mismatched");
			return CUDA_FAILED; 
		}
		if (deviceCount == 0)
		{
			Ogre::LogManager::getSingleton().logMessage("FAILED! There is no CUDA device available!");	
			return CUDA_FAILED;
		}
		
		// get CUDA version
		int driverVersion = 0, runtimeVersion = 0;     
		cudaDriverGetVersion(&driverVersion);		
		cudaRuntimeGetVersion(&runtimeVersion);
		
		// get CUDA device properties	
		cudaDeviceProp deviceProp;
		cudaGetDeviceProperties(&deviceProp, 0);	
		
		std::stringstream strDriverVersion; 
		std::stringstream strRuntimeVersion;
		std::stringstream strCUDACapVersion;
		strDriverVersion << driverVersion/1000 << "." << driverVersion%100; 
		strRuntimeVersion << runtimeVersion/1000 << "." << runtimeVersion%100; 
		strCUDACapVersion << deviceProp.major << "." << deviceProp.minor; 
		
		std::stringstream strGlobalMemMb; 
		strGlobalMemMb << deviceProp.totalGlobalMem/1024; 
		
		std::stringstream strConstMemMb; 
		strConstMemMb << deviceProp.totalConstMem/1024;  
		
		std::stringstream strSharedMemPerBlockMb; 
		strSharedMemPerBlockMb << deviceProp.sharedMemPerBlock / 1024; 
		
		std::stringstream strRegsPerBlock; 
		strRegsPerBlock << deviceProp.regsPerBlock; 
		
		std::stringstream strWarpSize; 
		strWarpSize << deviceProp.warpSize; 

		std::stringstream strMaxThreadsPerBlock; 
			std::stringstream strMaxThreadsPerBlockX;
			std::stringstream strMaxThreadsPerBlockY;
			std::stringstream strMaxThreadsPerBlockZ; 
		strMaxThreadsPerBlock << deviceProp.maxThreadsPerBlock; 
		strMaxThreadsPerBlockX << deviceProp.maxThreadsDim[0]; 
		strMaxThreadsPerBlockY << deviceProp.maxThreadsDim[1]; 
		strMaxThreadsPerBlockZ << deviceProp.maxThreadsDim[2]; 

		std::stringstream strMaxGridSizeX; 
		std::stringstream strMaxGridSizeY; 
		std::stringstream strMaxGridSizeZ; 
		strMaxGridSizeX << deviceProp.maxGridSize[0]; 
		strMaxGridSizeY << deviceProp.maxGridSize[1]; 
		strMaxGridSizeZ << deviceProp.maxGridSize[2]; 
		
		std::stringstream strMaxMemPitch; 
		strMaxMemPitch << deviceProp.memPitch; 
		
		std::stringstream stdTextureAlign; 
		stdTextureAlign << deviceProp.textureAlignment; 
		
		std::stringstream strClockRate; 
		strClockRate << deviceProp.clockRate;

		std::stringstream strComputeMode; 
		std::string str = 
			deviceProp.computeMode == cudaComputeModeDefault ?
			"Default (multiple host threads can use this device simultaneously)" :
			deviceProp.computeMode == cudaComputeModeExclusive ?
			"Exclusive (only one host thread at a time can use this device)" :
			deviceProp.computeMode == cudaComputeModeProhibited ?
			"Prohibited (no host thread can use this device)" :
			"Unknown";
		strComputeMode << str;
		
		return CUDA_SUCCESS; 
	}
	
	
	
}